package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.CarPackageAuditMapper;
import cn.wolfcode.car.business.query.CarPackageAuditQuery;
import cn.wolfcode.car.business.service.IBpmnInfoService;
import cn.wolfcode.car.business.service.ICarPackageAuditService;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.github.pagehelper.PageHelper;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class CarPackageAuditServiceImpl implements ICarPackageAuditService {

    @Autowired
    private CarPackageAuditMapper carPackageAuditMapper;

    @Autowired
    private IBpmnInfoService bpmnInfoService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    IServiceItemService serviceItemService;


    @Override
    public TablePageInfo<CarPackageAudit> query(CarPackageAuditQuery qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        return new TablePageInfo<CarPackageAudit>(carPackageAuditMapper.selectForList(qo));
    }


    @Override
    public void save(CarPackageAudit carPackageAudit) {
        carPackageAuditMapper.insert(carPackageAudit);
    }

    @Override
    public CarPackageAudit get(Long id) {
        return carPackageAuditMapper.selectByPrimaryKey(id);
    }


    @Override
    public void update(CarPackageAudit carPackageAudit) {
        carPackageAuditMapper.updateByPrimaryKey(carPackageAudit);
    }

    @Override
    public void deleteBatch(String ids) {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            carPackageAuditMapper.deleteByPrimaryKey(dictId);
        }
    }

    @Override
    public List<CarPackageAudit> list() {
        return carPackageAuditMapper.selectAll();
    }

    @Override
    public InputStream getProcessImageByAuditId(Long id) {

        //根据流程实例id，查询审核记录表，流程定义的id
        CarPackageAudit audit = carPackageAuditMapper.selectByPrimaryKey(id);

        BpmnInfo bpmnInfo = bpmnInfoService.get(audit.getBpmnInfoId());
        InputStream inputStream = null;
        //更加流程文件使用代码方式画出来
        BpmnModel model = repositoryService.getBpmnModel(bpmnInfo.getActProcessId());
        ProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        //1:审核中
        if(CarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus())){

            Task task = taskService.createTaskQuery()
                    .processInstanceId(audit.getInstanceId()).singleResult();
            List<String> activeActivityIds =
                    runtimeService.getActiveActivityIds(task.getExecutionId());

            inputStream = generator.generateDiagram(model, activeActivityIds,
                    Collections.EMPTY_LIST,
                    "宋体","宋体","宋体");
        }else{
            //2：审核结束
            inputStream = generator.generateDiagram(model, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
                    "宋体","宋体","宋体");
        }
        return inputStream;
    }


    @Override
    public void cancelApply(Long id) {

        //撤销操作
        /**思路：
         * 1.首先将服务单项状态改为初始化
         * 2.审核记录表中的状态改为撤销状态
         * 3.将流程实例对象删除掉，使用运行时对象RuntimeService
         */

        //进行逻辑判断，只有在审核中的才可以进行撤销
        CarPackageAudit audit = carPackageAuditMapper.selectByPrimaryKey(id);

        if ( audit == null || !CarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus())) {

            throw new BusinessException("参数异常");
        }

        //1.服务单项状态设置为初始化
        serviceItemService.changeStatus(audit.getServiceItemId(), ServiceItem.AUDITSTATUS_INIT);

        //2.审核记录对象的状态设置为撤销状态
        audit.setStatus(CarPackageAudit.STATUS_CANCEL);
        carPackageAuditMapper.updateByPrimaryKey(audit);

        //3.删除审核流程实例
        runtimeService.deleteProcessInstance(audit.getInstanceId(),"审核被撤销了");

    }


    @Override
    public void audit(Long id, int auditStatus, String auditRecord) {
        //审批实现(涉及到什么表):流程任务表

        //需要增加逻辑，当前的登录用户要和审核用户一致,并且当前任务的状态为审核中
        //根据传递进来的审核记录id，获取对应的处理人id
        //满足的条件，当前审核记录对象的状态为审核中，并且登录用户和处理人一致才可以
        CarPackageAudit audit = carPackageAuditMapper.selectByPrimaryKey(id);

        if (audit == null || !CarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus()) ||
                !audit.getAuditorId().equals(ShiroUtils.getUserId())){
            throw  new BusinessException("参数异常");
        }

        //不管审核记录的结果是怎么样的，都审核了任务，需要记录审核时间
        audit.setAuditTime(new Date());

        // 还有审核记录对象的变动,备注的变动,审核的时间
        //流程定义表 bpmn_info 流程任务表 task 审核记录表

        //流程往下走--task往下执行，审核记录对象的变动，审核备注，审核时间

        //假如店长审核通过后，做什么？
        //马上判断是否有下一个节点，，如果有设置下一个审核人，状态设置为审核中
        //没有流程结束，审核通过，状态设置为审核通过
        //服务单项设置为审核通过
        if (auditStatus == 2){
            //审核通过
            auditRecord = "【"+ShiroUtils.getUser().getUserName()+"同意，审核备注："+auditRecord+"】";
        }else {

            //审核不通过
            auditRecord = "【"+ShiroUtils.getUser().getUserName()+"拒绝，审核备注："+auditRecord+"】";
        }
        if (audit.getAuditRecord() == null){

            audit.setAuditRecord(auditRecord);
        }else {
            audit.setAuditRecord(audit.getAuditRecord()+","+auditRecord);
        }


        //流程往下走，task执行,根据流程id向下执行
        Task task = taskService.createTaskQuery()
                .processInstanceId(audit.getInstanceId())
                .singleResult();

        System.out.println(audit.getStatus());
        //设置流程分支条件值，审核通过还是审核拒绝
        // (这一步是店长审核完，马上进入分支点，告诉流程往下执行的态度)
        //这里是是流程分支条件，审核通过还是拒绝
        taskService.setVariable(task.getId(),"auditStatus",auditStatus);

        //设置流程的备注
        //通过流程任务的id  流程实例的id  以及设置备注
        taskService.addComment(task.getId(),task.getProcessInstanceId(),auditRecord);

        //执行任务，推动流程执行  -- 任务id
        taskService.complete(task.getId());

        //判断是否有下一个节点
        Task nextTask = taskService.createTaskQuery().processInstanceId(audit.getInstanceId())
                .singleResult();


        //条件为：状态为审核通过
        if (auditStatus == 2){
            if (nextTask !=null){
                //如果有下一个节点
                //审核记录对象变动，设置下一个节点审核人,这里设置的是审核人的id
                //因为表的设计就是存储审核人的id即可，根据id，可以查询到审核人
                String assignee = nextTask.getAssignee();
                audit.setAuditorId(Long.parseLong(assignee));

            }else {
                //没有下一个节点
                //审核记录对象的状态设置为--审核通过
                audit.setStatus(CarPackageAudit.STATUS_PASS);
                //养修服务套餐状态设置为--审核通过
                serviceItemService.changeStatus(audit.getServiceItemId(),ServiceItem.AUDITSTATUS_APPROVED);
            }

        }else {
            //审核拒绝做什么？

            //1.流程结束（无需处理）
            //2.审核记录对象状态设置为审核拒绝
            audit.setStatus(CarPackageAudit.STATUS_REJECT);
            //3.养修服务单项设置为初始化状态
            serviceItemService.changeStatus(audit.getServiceItemId(),ServiceItem.AUDITSTATUS_INIT);

        }
        //4.修改审核记录对象的信息
        carPackageAuditMapper.updateByPrimaryKey(audit);
    }

}
